import EditTool from "./lib/EditTool.js";
import * as geometryEngine from "@geoscene/core/geometry/geometryEngine";
import * as webMercatorUtils from "@geoscene/core/geometry/support/webMercatorUtils.js";
import Point from "@geoscene/core/geometry/Point.js";
import Polygon from "@geoscene/core/geometry/Polygon.js";
import Graphic from "@geoscene/core/Graphic.js";
import MathStuff from "./lib/MathStuff.js";
import { editSymbol } from "./lib/symbol";
import { measureArea, measureDistance } from "./lib/MeasureTool.js";
import MixGraphicsLayer from "./MixGraphicsLayer.js";

interface PicturePointOptions {
  pointArray: Array<number>;
  iconType?: string;
  width?: number;
  height?: number;
}


interface TextPointOptions{
  pointArray: Array<number>;
  text?: string;
  fontSize?: number;
  fontColor?: string;
  titleTip?: string;
}

interface LineOptions{
  pathsArray: Array<Array<number>>;
  width?: number;
  color?: string;
}

interface PolygonOptions{
  ringsArray?: Array<Array<number>>;
  pointArray?: Array<number>;
  radius?: number;
  borderWidth?: number;
  borderColor?: string;
  fillColor?: string;
}

interface AllGraphicOptions {
  type: string;
  point?: PicturePointOptions
  text?: TextPointOptions;
  line?: LineOptions;
  polygon?: PolygonOptions;
}



export default class MixEditTool extends EditTool {
  callBack: any = [];
  distanceMeasure: any = null;
  areaMeasure: any = null;
  viewType: string = "2d";
  arrowType: string = "";
  arrowPoints: any = [];
  allFuntions: any = {};
  mathStuff: MathStuff = new MathStuff();
  tempLayer: MixGraphicsLayer = new MixGraphicsLayer({id: "mixEditTempLayer"});
  allGraphicOptions: AllGraphicOptions;

  constructor(options = { config: {} }) {
    super(options);
    this.viewType = this.appConfig.activeView.type;
    this.distanceMeasure = measureDistance(this.appConfig.activeView);
    this.areaMeasure = measureArea(this.appConfig.activeView);
    this.appConfig.activeView.map.add(this.tempLayer);
    this.sketchViewModel.layer = this.tempLayer;

    this.init();
  }

  /**
   *@Description: 初始化函数
   *@Parameters:
   *@MethodAuthor: yfyang
   *@Date: 2024-02-27 08:58:03
   */
  init() {
    //监听sketchViewModel 的创建事件
    this.sketchViewModel.on("create", (evt) => {
      this.modeCreateFun(evt);
    });
    this.sketchViewModel.on("update", (evt) => {
      this.modeUpdateFun(evt);
    });
    this.appConfig.activeView.on("click", (event:any) => {
      this.appConfig.activeView.hitTest(event).then(function (response: any) {
        console.log("click response:", response);
        
        const graphicHits = response.results?.filter(
          (hitResult: any) => hitResult.type === "graphic" && hitResult.graphic.layer === "mixEditTempLayer"
        );
        if (graphicHits?.length > 0) {
          graphicHits.forEach((graphicHit:any) => {
             console.log('mixEditTempLayer.hit',graphicHit.graphic);
          });
        }
      });
    });
    this.allFuntions = {
      "point":()=> this.createPoint(), // 点
      "polyline":()=>  this.createPolyline(), // 线
      "polygon":()=>  this.createPolygon(), // 面
      "circle": ()=> this.createCircle(), // 圆
      "rectangle": ()=> this.createRectangle(), // 矩形
      "single-arrow":()=>  this.createSingleArrow(), // 单箭头
      "double-arrow": ()=> this.createDoubleArrow(), // 双箭头
      "distance-measure": ()=> this.beginDistanceMeasure(), // 距离测量
      "area-measure": ()=> this.beginAreaMeasure(), // 面积测量
      "clear":()=>  this.clear(), // 清除
      "undo": ()=> this.undo(), // 撤销
      "redo": ()=> this.redo(), // 重做
      "cancel":()=>  this.cancel(), // 取消
      "complete": this.complete(), // 完成
      "addGraphic":(graphic: Graphic)=>  this.addGraphic(graphic), // 添加图形
      "removeGraphic": (graphic: Graphic)=> this.removeGraphic(graphic), // 移除图形
      "measureClear": ()=> this.measureClear(), // 清除测量
    }
  }

  excute(type: string,options: any) {
    if (type in this.allFuntions) {
      return this.allFuntions[type](options);
    }else if(type in this.tempLayer.allCreateFunction){
        return this.tempLayer.excute(type,options);
    }
  }


  setAllGraphicOptions(options: AllGraphicOptions): void {
    this.allGraphicOptions = options;
  }


  vertexCovertingFun(addedVertex: Array<any>): Point {
    let addPoint: Point = new Point({
      x: addedVertex[0],
      y: addedVertex[1],
      spatialReference: this.appConfig.activeView.spatialReference,
    });
    // 如果需要 WGS84 坐标，进行转换
    let addPointWGS84: Point;
    if (this.appConfig.activeView.spatialReference.isWebMercator) {
      addPointWGS84 = webMercatorUtils.webMercatorToGeographic(
        addPoint
      ) as Point;
    } else {
      // 如果地图已经是地理坐标系，直接使用
      addPointWGS84 = addPoint;
    }
    return addPointWGS84;
  }

  modeCreateFun(event: any) {
    // let that: MilitaryEditTool = this;

    let eventInfo = event.toolEventInfo;

    if (eventInfo && eventInfo.type === "vertex-add") {
      let addedVertex: Array<any> = eventInfo.added[0];
      if (this.arrowType !== "") {
        this.arrowPoints.push(this.vertexCovertingFun(addedVertex));
      }
      
      if (
        (this.arrowType === "single" || this.arrowType === "double") &&
        this.arrowPoints.length === 2
      ) {
        let arrowLine = this.mathStuff.arrow2(
          this.arrowPoints[0],
          this.arrowPoints[1]
        );
        let arrowGraphic: Graphic = new Graphic({
          geometry: new Polygon({
            rings: arrowLine,
          }),
          symbol: editSymbol.pgcreateSymbol,
        });

        if (this.arrowType === "single") this.sketchViewModel.complete();
        this.tempLayer.remove(event.graphic);
        this.tempLayer.add(arrowGraphic);
      }
      if (this.arrowType === "double" && this.arrowPoints.length == 3) {
        let arrowLine = this.mathStuff.arrow2(
          this.arrowPoints[0],
          this.arrowPoints[1]
        );
        let arrowLine2 = this.mathStuff.arrow2(
          this.arrowPoints[0],
          this.arrowPoints[2]
        );
        let arrowGeometry: Polygon = new Polygon({
          rings: arrowLine,
        });
        let arrowGeometry2: Polygon = new Polygon({
          rings: arrowLine2,
        });
        let unionPolyon = geometryEngine.union([arrowGeometry, arrowGeometry2]);
        let arrowGraphic: Graphic = new Graphic({
          geometry: unionPolyon,
          symbol: editSymbol.pgcreateSymbol,
        });

        this.sketchViewModel.complete();
        this.tempLayer.remove(event.graphic);
        this.tempLayer.add(arrowGraphic);
      }
    }

    if (event.state === "active") {
      let addedVertex: Array<any> = eventInfo.coordinates;
      if (!addedVertex) return;
      let addPointWGS84 = this.vertexCovertingFun(addedVertex);

      if (
        (this.arrowType === "single" || this.arrowType === "double") &&
        this.arrowPoints.length === 1
      ) {
        let arrowLine = this.mathStuff.arrow2(
          this.arrowPoints[0],
          addPointWGS84
        );
        let arrowGraphic: Graphic = new Graphic({
          geometry: new Polygon({
            rings: arrowLine,
          }),
          symbol: editSymbol.pgcreateSymbol,
        });
        this.tempLayer.remove(event.graphic);
        this.tempLayer.add(arrowGraphic);
      }
      if (this.arrowType === "double" && this.arrowPoints.length === 2) {
        let arrowLine1 = this.mathStuff.arrow2(
          this.arrowPoints[0],
          this.arrowPoints[1]
        );
        let arrowLine2 = this.mathStuff.arrow2(
          this.arrowPoints[0],
          addPointWGS84
        );
        let arrowPolyon1 = new Polygon({
          rings: arrowLine1,
        });
        let arrowPolyon2 = new Polygon({
          rings: arrowLine2,
        });
        let unionPolyon = geometryEngine.union([arrowPolyon1, arrowPolyon2]);
        let arrowGraphic: Graphic = new Graphic({
          geometry: unionPolyon,
          symbol: editSymbol.pgcreateSymbol,
        });
        this.tempLayer.remove(event.graphic);
        this.tempLayer.add(arrowGraphic);
      }
    }

    if (event.state === "complete") {
      this.arrowType = "";
      this.arrowPoints = [];
      this.tempLayer.drawGraphics.push({
        type:"draw-vector",
        graphic:event.graphic
      });
      if (this.callBack.length > 0) {
        this.callBack.forEach((fun: Function) => {
          fun(event.graphic);
        });
      }
    }
  }

  modeUpdateFun(event: any) {
    console.log("update event:", event);
    
  }

  setCallBackMethod(fun: Function): void {
    this.callBack.push(fun);
  }

  createPoint(): void {
    this.createFeature("point", "click");
  }

  createPolyline(): void {
    this.createFeature("polyline", "click");
  }

  createPolygon(): void {
    this.createFeature("polygon", "click");
  }

  createCircle(): void {
    this.createFeature("circle", "click");
  }

  createRectangle(): void {
    this.createFeature("rectangle", "click");
  }

  createSingleArrow(): void {
    this.arrowType = "single";
    this.createFeature("polyline", "click");
  }

  createDoubleArrow(): void {
    this.arrowType = "double";
    this.createFeature("polyline", "click");
  }

  beginDistanceMeasure(): void {
    this.distanceMeasure.start();
  }

  beginAreaMeasure(): void {
    this.areaMeasure.start();
  }

  measureClear(): void {
    this.distanceMeasure.clear();
    this.areaMeasure.clear();
  }

  clear(): void {
    this.sketchViewModel.cancel();
    this.tempLayer.removeAll();
  }

  addGraphic(graphic: Graphic): void {
    this.tempLayer.add(graphic);
  }

  removeGraphic(graphic: Graphic): void {
    this.tempLayer.remove(graphic);
  }
}
